package com.shengzhe.ostudent.utils.jdbc;

import com.shengzhe.ostudent.common.enums.StateEnum;
import com.shengzhe.ostudent.entity.base.BaseEntity;
import com.shengzhe.ostudent.utils.OsBeanUtils;
import com.shengzhe.ostudent.utils.page.PageEntity;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

public class DaoUtils {


    /**
     * 通用插入方法
     *
     * @param entity 传入的实体类
     * @return 插入行数
     */
    public static int insert(Object entity) {
        // 获取实体类的所有声明字段，包括私有字段
        Class<?> clazz = entity.getClass();

        StringBuilder columnNames = new StringBuilder();
        StringBuilder paramValues = new StringBuilder();

        List<Object> paramsList = new ArrayList<>();

        for (Field field : OsBeanUtils.getPrivateFields(clazz)) {
            // 允许访问私有字段
            field.setAccessible(true);

            String name = field.getName();
            Object value;

            try {
                if (name.equals("createTime") || name.equals("updateTime")) {
                    field.set(entity, new Date());
                }
                value = field.get(entity);
            } catch (IllegalArgumentException | IllegalAccessException e) {
                throw new RuntimeException("@Error when getting value of " + name, e);
            }

            if (!Objects.isNull(value)) {
                // 后续可以对value进行适当的处理，比如替换特殊字符等
                columnNames.append("`").append(name).append("`, ");
                paramValues.append("?, ");
                paramsList.add(value);
            }
        }

        if (columnNames.length() > 0) {
            columnNames.setLength(columnNames.length() - 2); // removing the last comma
            paramValues.setLength(paramValues.length() - 2); // removing the last comma
        }

        String insertSql = "INSERT INTO " + clazz.getSimpleName().toLowerCase() + " (" +
                columnNames +
                ") VALUES (" +
                paramValues +
                ")";
        return JDBCUtils.executeUpdate(insertSql, paramsList.toArray());
    }

    /**
     * 通用更新方法
     *
     * @param entity 传入的实体类
     * @return 更新行数
     */
    public static int updateById(Object entity) {
        try {
            // 获取实体类中的id字段
            Field field = BaseEntity.class.getDeclaredField("id");
            field.setAccessible(true);
            long id = Long.parseLong(String.valueOf(field.get(entity)));
            // 构建条件对象
            WhereSql whereSql = new WhereSql().and("id", id);

            // id不更新
            field.set(entity, null);

            // 调用通用更新方法
            return update(entity, whereSql);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 通用更新方法
     *
     * @param entity 传入的实体类
     * @return 更新行数
     */
    public static int update(Object entity, WhereSql whereSql) {
        // 获取实体类的所有声明字段，包括私有字段
        Class<?> clazz = entity.getClass();

        StringBuilder columnNamesAndValues = new StringBuilder();

        List<Object> paramsList = new ArrayList<>();

        for (Field field : OsBeanUtils.getPrivateFields(clazz)) {
            // 允许访问私有字段
            field.setAccessible(true);

            String name = field.getName();
            Object value;

            try {
                if (name.equals("updateTime")) {
                    field.set(entity, new Date());
                }
                value = field.get(entity);
            } catch (IllegalArgumentException | IllegalAccessException e) {
                throw new RuntimeException("@Error when getting value of " + name, e);
            }

            if (value != null) {
                // 后续可以对value进行适当的处理，比如替换特殊字符等
                columnNamesAndValues.append("`").append(name).append("` = ?, ");
                paramsList.add(value);
            }
        }

        if (columnNamesAndValues.length() > 0) {
            columnNamesAndValues.setLength(columnNamesAndValues.length() - 2); // removing the last comma
        }

        String updateSql = "UPDATE " + clazz.getSimpleName().toLowerCase() +
                " SET " + columnNamesAndValues;
        return JDBCUtils.executeUpdate(updateSql, whereSql, paramsList.toArray());
    }

    /**
     * 通用硬删方法
     *
     * @param entity 传入的实体类
     * @return 影响行数
     */
    public static int delete(Object entity, WhereSql whereSql) {
        // 获取实体类的所有声明字段，包括私有字段
        Class<?> clazz = entity.getClass();


        String deleteSql = "DELETE FROM " + clazz.getSimpleName().toLowerCase();
        return JDBCUtils.executeUpdate(deleteSql, whereSql);
    }

    public static int deleteById(Object entity) {
        try {
            // 获取实体类中的id字段
            Field field = BaseEntity.class.getDeclaredField("id");
            field.setAccessible(true);
            long id = Long.parseLong(String.valueOf(field.get(entity)));
            // 构建条件对象
            WhereSql whereSql = new WhereSql().and("id", id);

            return delete(entity, whereSql);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 通用软删方法
     *
     * @param entity    传入的实体类
     * @param stateEnum 软删状态
     * @return 影响行数
     */
    public static int logicalDelete(Object entity, StateEnum stateEnum, WhereSql whereSql) {
        // 获取实体类的所有声明字段，包括私有字段
        Class<?> clazz = entity.getClass();


        String logicalDeleteSql = "UPDATE " + clazz.getSimpleName().toLowerCase() + " SET state = " + stateEnum.getState();
        return JDBCUtils.executeUpdate(logicalDeleteSql, whereSql);
    }

    public static int logicalDeleteById(Object entity) {
        try {
            // 获取实体类中的id字段
            Field field = BaseEntity.class.getDeclaredField("id");
            field.setAccessible(true);
            long id = Long.parseLong(String.valueOf(field.get(entity)));
            // 构建条件对象
            WhereSql whereSql = new WhereSql().and("id", id);

            return logicalDelete(entity, whereSql);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 通用软删方法
     *
     * @param entity 传入的实体类
     * @return 影响行数
     */
    public static int logicalDelete(Object entity, WhereSql whereSql) {
        // 获取实体类的所有声明字段，包括私有字段
        Class<?> clazz = entity.getClass();


        String logicalDeleteSql = "UPDATE " + clazz.getSimpleName().toLowerCase() + " SET state = 0";
        return JDBCUtils.executeUpdate(logicalDeleteSql, whereSql);
    }

    public static ResultSet query(String key, WhereSql whereSql, Object... params) {
        // 从配置文件获取sql
        String sql = JDBCUtils.getSql(key);
        return JDBCUtils.executeQuery(sql, whereSql, params);
    }

    public static <T> T query(Class<T> clazz, WhereSql whereSql) {
        // 获取实体类的所有私有字段
        StringBuilder columnNames = new StringBuilder();


        for (Field field : OsBeanUtils.getPrivateFields(clazz)) {
            // 允许访问私有字段
            field.setAccessible(true);

            String name = field.getName();


            // 后续可以对value进行适当的处理，比如替换特殊字符等
            columnNames.append("`").append(name).append("` , ");
        }

        if (columnNames.length() > 0) {
            columnNames.setLength(columnNames.length() - 2); // removing the last comma
        }

        String selectSql = "SELECT " + columnNames + " FROM " + clazz.getSimpleName().toLowerCase();
        return OsBeanUtils.resultSetToBean(JDBCUtils.executeQuery(selectSql, whereSql), clazz);
    }


    public static <T> List<T> queryList(Class<T> clazz, WhereSql whereSql) {
        // 获取实体类的所有私有字段
        StringBuilder columnNames = new StringBuilder();


        for (Field field : OsBeanUtils.getPrivateFields(clazz)) {
            // 允许访问私有字段
            field.setAccessible(true);

            String name = field.getName();


            // 后续可以对value进行适当的处理，比如替换特殊字符等
            columnNames.append("`").append(name).append("` , ");
        }

        if (columnNames.length() > 0) {
            columnNames.setLength(columnNames.length() - 2); // removing the last comma
        }

        String selectSql = "SELECT " + columnNames + " FROM " + clazz.getSimpleName().toLowerCase();
        return OsBeanUtils.resultSetToList(JDBCUtils.executeQuery(selectSql, whereSql), clazz);
    }

    public static <T> List<T> queryPage(Class<T> clazz, WhereSql whereSql, PageEntity pageEntity) {
        // 获取实体类的所有私有字段
        StringBuilder columnNames = new StringBuilder();


        for (Field field : OsBeanUtils.getPrivateFields(clazz)) {
            // 允许访问私有字段
            field.setAccessible(true);

            String name = field.getName();


            // 后续可以对value进行适当的处理，比如替换特殊字符等
            columnNames.append("`").append(name).append("` , ");
        }

        if (columnNames.length() > 0) {
            columnNames.setLength(columnNames.length() - 2); // removing the last comma
        }
        String selectSql = "SELECT " + columnNames + " FROM " + clazz.getSimpleName().toLowerCase() +
                whereSql.getStringWhereSql() + " LIMIT " + (pageEntity.getPageNum() - 1) * pageEntity.getPageSize() + "," + pageEntity.getPageSize();
        return OsBeanUtils.resultSetToList(JDBCUtils.executeQuery(selectSql), clazz);
    }

    public static ResultSet queryPage(String key, WhereSql whereSql, PageEntity pageEntity) {
        String sql = JDBCUtils.getSql(key);
        String selectSql = sql + whereSql.getStringWhereSql() +
                " LIMIT " + (pageEntity.getPageNum() - 1) * pageEntity.getPageSize() + "," + pageEntity.getPageSize();
        return JDBCUtils.executeQuery(selectSql);
    }

    /**
     * count方法
     *
     * @param clazz     对应表的实体类
     * @param condition 条件构造类
     * @return count
     */
    public static long count(Class<?> clazz, Object condition) {
        String countSql = "SELECT COUNT(1) FROM " + clazz.getSimpleName().toLowerCase();
        WhereSql whereSql = WhereSql.buildAnd(condition);
        Long count = OsBeanUtils.resultSetToLong(JDBCUtils.executeQuery(countSql, whereSql));
        return Objects.isNull(count) ? 0 : count;
    }
}
